#pragma once
#include <map>
#include <Login_Process.h>

class InputEntry
{
	struct _KEY_
	{
		char c[3];
		_KEY_(char a = 0, char b = 0)
		{
			c[0] = a;
			c[1] = b;
			c[2] = 0;
		}
	};

	Input_Process::_INPUT_FUNCTION_		_M_func;
	
	_INPUT_DESC_						_M_ms;
public:
	InputEntry() = default;
	~InputEntry() = default;
	UINT								_M_version;
	std::shared_mutex*					_M_mutex;
	static _MT_SAFE_<RECT>*				_M_screen_rect;


	void init(_LOGIN_CONF_&  ref)
	{
		_M_version			= ref.version;
		_M_func				= ref.input_handle.func;
		_M_mutex			= ref.input_handle.mutex_ptr;
		_M_screen_rect		= ref.input_handle.rect_ptr;
		_M_ms.type			= mouse;
		initUniqueSymbols();
	}

	void sendCharater(char c)
	{
		auto charKey = charToVirtualKey(c);
		pressKey(charKey.c);
	}

	void sendControl(char c)
	{
		_KEY_ key(c);
		pressKey(key.c);
	}

	void setCursorPosition(int x, int y)
	{
		_M_ms.ms.button			= 0;
		_M_ms.ms.state			= 0;
		RECT rect = _M_screen_rect->get();
		_M_ms.ms.x_abs			= (float) x / (rect.right - rect.left);
		_M_ms.ms.y_abs			= (float) y / (rect.bottom - rect.top);//
		_M_func(_M_ms, FALSE);
	}

	void mouseClick()
	{
		mouseClick_v2();
	}

	void mouseClick_v1()
	{
		//printf("[ATL]%d %d\n", (int)(_M_ms.ms.x_abs * 1360), (int)(_M_ms.ms.y_abs * 768));
		_M_ms.ms.button = 1;
		_M_ms.ms.state = 7;
		_M_func(_M_ms, FALSE);
		//Sleep(10);
		_M_ms.ms.state = 8;
		_M_func(_M_ms, FALSE);
		//Sleep(10);

#ifndef _DEBUG
		POINT pt;
		GetCursorPos(&pt);
		//printf("[LN]mouse click down(%d, %d) up(%d, %d)\n"
		//	, (int)(_M_ms.ms.x_abs * 1360),(int)(_M_ms.ms.y_abs * 768), pt.x, pt.y);
#endif
	}

	void mouseClick_v2()
	{
		_M_ms.ms.button = 1;
		_M_ms.ms.state = 1;
		_M_func(_M_ms , FALSE);
		Sleep(5);

		_M_ms.ms.button = 0;
		_M_ms.ms.state = 2;
		_M_func(_M_ms, FALSE);
		Sleep(5);

#ifdef _DEBUG
		POINT pt;
		GetCursorPos(&pt);
		printf("[LN]mouse click (%d, %d)\n", pt.x, pt.y);
#endif
	}

private:
	std::map<char, _KEY_> UniqueSymbol;
	void initUniqueSymbols()
	{
		UniqueSymbol[0]		= _KEY_();
		UniqueSymbol[';']	= _KEY_( VK_OEM_1);
		UniqueSymbol[':']	= _KEY_( VK_LSHIFT, VK_OEM_1 );
		UniqueSymbol['=']	= _KEY_( VK_OEM_PLUS );
		UniqueSymbol['+']	= _KEY_( VK_LSHIFT, VK_OEM_PLUS );
		UniqueSymbol[',']	= _KEY_( VK_OEM_COMMA );
		UniqueSymbol['<']	= _KEY_( VK_LSHIFT, VK_OEM_COMMA );
		UniqueSymbol['-']	= _KEY_( 189 );
		UniqueSymbol['_']	= _KEY_( VK_LSHIFT, 189 );
		UniqueSymbol['.']	= _KEY_( 190 );
		UniqueSymbol['>']	= _KEY_( VK_LSHIFT, 190 );
		UniqueSymbol['/']	= _KEY_( 191 );
		UniqueSymbol['?']	= _KEY_( VK_LSHIFT, 191 );
		UniqueSymbol['`']	= _KEY_( 192 );
		UniqueSymbol['~']	= _KEY_( VK_LSHIFT, 192 );
		UniqueSymbol['[']	= _KEY_( 219 );
		UniqueSymbol['{']	= _KEY_( VK_LSHIFT, 219 );
		UniqueSymbol['\\']	= _KEY_( 220 );
		UniqueSymbol['|']	= _KEY_( VK_LSHIFT, 220 );
		UniqueSymbol[']']	= _KEY_( 221 );
		UniqueSymbol['}']	= _KEY_( VK_LSHIFT, 221 );
		UniqueSymbol['\'']	= _KEY_( 222 );
		UniqueSymbol['\"']	= _KEY_( VK_LSHIFT, 222 );
		UniqueSymbol['!']	= _KEY_( VK_LSHIFT, '1');
		UniqueSymbol['@']	= _KEY_( VK_LSHIFT, '2');
		UniqueSymbol['#']	= _KEY_( VK_LSHIFT, '3');
		UniqueSymbol['$']	= _KEY_( VK_LSHIFT, '4');
		UniqueSymbol['%']	= _KEY_( VK_LSHIFT, '5');
		UniqueSymbol['^']	= _KEY_( VK_LSHIFT, '6');
		UniqueSymbol['&']	= _KEY_( VK_LSHIFT, '7');
		UniqueSymbol['*']	= _KEY_( VK_LSHIFT, '8');
		UniqueSymbol['(']	= _KEY_( VK_LSHIFT, '9');
		UniqueSymbol[')']	= _KEY_( VK_LSHIFT, '0');
		UniqueSymbol[' '] = _KEY_(VK_SPACE);
	}

	void pressKey(char* ptr)
	{
		pressKey_v2(ptr);
	}

	void pressKey_v1(char* ptr)
	{
		if (*ptr == 0)
		{
			return;
		}
		_INPUT_DESC_ ki = { keyboard };
		ki.kb.len = 2;
		ki.kb.buff = new BYTE[2];
		ki.kb.buff[0] = *ptr;
		ki.kb.buff[1] = 3;
		_M_func(ki, FALSE);
		Sleep(10);
		pressKey_v1(ptr + 1);

		ki.kb.buff = new BYTE[2];
		ki.kb.buff[0] = *ptr;
		ki.kb.buff[1] = 4;
		_M_func(ki, FALSE);
		Sleep(10);
#ifndef _DEBUG
		//printf("[LN]press key (%d)\n", *ptr);
#endif
	}

	void pressKey_v2(char* ptr)
	{
		_INPUT_DESC_ ki = { keyboard };
		ki.kb.buff = new BYTE[3];
		ki.kb.len = 0;
		for (UINT i = 0; ptr[i] != 0; ++i)
		{
			ki.kb.buff[i] = ptr[i];
			++ki.kb.len;
		}
		ki.kb.reset = 1;
		_M_func(ki, FALSE);

#ifdef _DEBUG
		POINT pt;
		GetCursorPos(&pt);
		printf("[LN]press key (%d, %d)\n", pt.x, pt.y);
#endif
	}


	_KEY_ charToVirtualKey(char c)
	{
		if (c >= 'a' && c <= 'z')
		{
			return _KEY_( c - 32 );
		}
		else if (c >= 'A' && c <= 'Z')
		{
			return _KEY_(VK_LSHIFT, c );
		}
		else if (c >= '0' && c <= '9')
		{
			return _KEY_( c );
		}
		else
		{
			auto itr = UniqueSymbol.find(c);
			return (itr == UniqueSymbol.end()) ? UniqueSymbol[0] : itr->second;
		}
	}
};

class INPUT_LOCKGUARD
{
public:
	INPUT_LOCKGUARD(InputEntry* input)
	{
		_M_input = input;
		_M_input->_M_mutex->lock();
		CapslkOn = (GetKeyState(VK_CAPITAL));
		if (CapslkOn == 1)
		{
			_M_input->sendControl(VK_CAPITAL);
		}
	}

	~INPUT_LOCKGUARD()
	{
		if (CapslkOn == 1)
		{
			_M_input->sendControl(VK_CAPITAL);
		}
		_M_input->_M_mutex->unlock();
		printf("[ATL]unlock input control!\n");
	}
private:
	short				CapslkOn;
	InputEntry*			_M_input;
};